{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook shows how to treat surface reactions in reacting systems where diffusion is a much faster process in comparison to the chemical reactions (surface is treated as a \"homogenized\" concentration)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from collections import defaultdict\n",
    "from chempy import ReactionSystem, Species, Reaction\n",
    "from chempy.units import to_unitless, SI_base_registry, rescale, default_constants as const, default_units as u\n",
    "from chempy.kinetics.ode import (\n",
    "    _create_odesys as create_odesys,\n",
    ")\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ads_token = '(ads)'\n",
    "phases = {'(aq)': 0, ads_token: 1}\n",
    "ads_comp = -1\n",
    "vacancy = Species('vacancy(ads)', composition={ads_comp: 1},\n",
    "                  phase_idx=phases[ads_token], latex_name='vacancy(ads)')\n",
    "\n",
    "def substance_factory(name):\n",
    "    if name == vacancy.name:\n",
    "        return vacancy\n",
    "    s = Species.from_formula(name, phases=phases)\n",
    "    if name.endswith(ads_token):\n",
    "        s.composition[ads_comp] = 1\n",
    "    return s\n",
    "\n",
    "rsys = ReactionSystem.from_string(\"\"\"\n",
    "vacancy(ads) + H2O2 -> H2O2(ads); 'k_ads_H2O2'\n",
    "H2O2(ads) + vacancy(ads) -> 2 OH(ads); 'k_split_H2O2ads'\n",
    "OH(ads) + H2O2 -> H2O + HO2 + vacancy(ads); 'k_abst_OHads_H2O2'\n",
    "HO2 + HO2 -> O2 + H2O2; 'k_disprop_HO2'\n",
    "\"\"\", substance_factory=substance_factory)\n",
    "rsys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ureg = SI_base_registry.copy()\n",
    "ureg['length'] = u.dm\n",
    "odesys, odesys_extra = create_odesys(rsys, unit_registry=ureg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "powder_mass = 42*u.g\n",
    "specific_surf_area = 35*u.m**2/u.g  # e.g. from BET\n",
    "sample_volume = 250*u.cm3\n",
    "surf_volume_ratio = powder_mass*specific_surf_area/sample_volume\n",
    "\n",
    "adsorption_cross_section = 0.162*u.nm**2  # N2 at 77K on active carbon\n",
    "conc_vacancy = rescale(surf_volume_ratio/(adsorption_cross_section * const.Avogadro_constant), u.molar)\n",
    "conc_vacancy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "c0 = defaultdict(lambda: 0*u.M, H2O2=.2*u.M, **{'vacancy(ads)': conc_vacancy})\n",
    "\n",
    "tend = 3600*u.s\n",
    "result, result_extra = odesys_extra['unit_aware_solve'](\n",
    "    (1e-7*u.s, tend), c0,\n",
    "    dict(\n",
    "        k_ads_H2O2=.1/u.M/u.s,\n",
    "        k_split_H2O2ads=.2/u.M/u.s,\n",
    "        k_abst_OHads_H2O2=.3/u.M/u.s,\n",
    "        k_disprop_HO2=.4/u.M/u.s\n",
    "    ), integrator='cvode'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, axes = plt.subplots(1, 2, figsize=(14, 4))\n",
    "result.plot(ax=axes[0])\n",
    "result.plot(ax=axes[1], xscale='log', yscale='log')\n",
    "for ax in axes:\n",
    "    #ax.set_ylabel('Concentration / M')\n",
    "    #ax.set_xlabel('Time / min')\n",
    "    ax.set_ylim(to_unitless([1e-6*u.molar, c0['H2O2']], result_extra['unit_conc']))\n",
    "    ax.set_xlim(to_unitless([1*u.s, tend], result_extra['unit_time']))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
